package com.zx.练习题._2020面试题;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class CP3 {

    private static final String[] ENGINES = {"百度", "360", "Google"};

    //3、【编码机试】同时执行3个方法，最终只要最早返回结果的数据，剩下两个方法忽略结果不要。
    public static void main(String[] args) {
        //使用CountDownLatch控制
        //func1();

        // 使用completableFuture实现
        //func2();

        // 使用队列实现，发布订阅模式
        func3();
    }

    private static void func1() {
        CountDownLatch cdl = new CountDownLatch(1);

        Random random = new Random();

        for (String engine : ENGINES) {
            new Thread(() -> {
                try {
                    Thread.sleep(random.nextInt(5) * 1000);
                    System.out.println(engine + ">>>>");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    cdl.countDown();
                }
            }).start();
        }

        try {
            cdl.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("func1 done");
    }

    private static void func2() {
        List<CompletableFuture<String>> futureList = new ArrayList<>();
        for (String engine : ENGINES) {
            CompletableFuture<String> future = CompletableFuture.completedFuture(engine)
                    .thenApplyAsync(e -> e + ">>>");
            futureList.add(future);
        }
        CompletableFuture<Object> future = CompletableFuture
                .anyOf(futureList.toArray(new CompletableFuture[futureList.size()]))
                .whenComplete((msg, e) -> System.out.println("func2 done"));

        future.join();

        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }

    private static void func3() {
        BlockingQueue<String> queue = new LinkedBlockingQueue<>(3);
        Random random = new Random();
        for (String engine : ENGINES) {
            new Thread(() -> {
                try {
                    Thread.sleep(random.nextInt(5) * 1000);
                    queue.offer(engine);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        try {
            System.out.println(queue.poll(10, TimeUnit.SECONDS));
            System.out.println("func3 done");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
